home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / ulimit.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  9KB  |  394 lines

  1. /* ulimit.c -- Setting resource usage for children of the shell. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include "shell.h"
  23.  
  24. #include <sys/types.h>
  25. #include <sys/errno.h>
  26. extern int errno;
  27.  
  28. #ifndef SYSV
  29. #include <sys/time.h>
  30. #include <sys/resource.h>
  31. #else
  32. #include <sys/times.h>
  33. #endif
  34.  
  35. /* **************************************************************** */
  36. /*                                    */
  37. /*            Ulimit builtin and Hacks.               */
  38. /*                                    */
  39. /* **************************************************************** */
  40.  
  41. /* Block size for ulimit operations. */
  42. #define ULIMIT_BLOCK_SIZE ((long)1024)
  43.  
  44. #define u_FILE_SIZE 1
  45. #define u_MAX_BREAK_VAL 3
  46. #define u_PIPE_SIZE 4
  47. #define u_CORE_FILE_SIZE 6
  48. #define u_DATA_SEG_SIZE 8
  49. #define u_PHYS_MEM_SIZE 10
  50. #define u_CPU_TIME_LIMIT 12
  51. #define u_STACK_SIZE 14
  52.  
  53. #ifndef RLIM_INFINITY
  54. #define RLIM_INFINITY  0x7fffffff
  55. #endif
  56.  
  57. typedef struct ResourceLimit {
  58.   struct ResourceLimit *next;
  59.   int cmd;
  60.   long limit;
  61. } RESOURCE_LIMIT;
  62.  
  63. RESOURCE_LIMIT *resource_limits = (RESOURCE_LIMIT *)NULL;
  64.  
  65. /* Called after we fork.  Sets the process resource limits to the
  66.    values saved in RESOURCE_LIMITS. */
  67. set_process_resource_limits ()
  68. {
  69.   long shell_ulimit ();
  70.   register RESOURCE_LIMIT *limits = resource_limits;
  71.  
  72.   while (limits)
  73.     {
  74.       shell_ulimit (limits->cmd, limits->limit, 1);
  75.       limits = limits->next;
  76.     }
  77. }
  78.  
  79. /* Report or set limits associated with certain per-process resources.
  80.    See the help documentation in builtins.c for a full description.
  81.    Chet Ramey & Brian Fox 3/13/89 */
  82. ulimit_builtin (list)
  83.      register WORD_LIST *list;
  84. {
  85.   long shell_ulimit ();
  86.   register char *s;
  87.   int c, setting, cmd, r = EXECUTION_SUCCESS;
  88.   long current_limit, real_limit, limit = -1L;
  89.   long block_factor;
  90.  
  91.   do
  92.     {
  93.       cmd = u_FILE_SIZE;
  94.       setting = 0;
  95.       block_factor = ULIMIT_BLOCK_SIZE;
  96.  
  97.       if (list)
  98.     {
  99.       s = list->word->word;
  100.       if (s && (*s == '-'))
  101.         {
  102.           c = *++s;
  103.  
  104.           if (!c || *++s)
  105.         goto error_case;
  106.  
  107.           list = list->next;
  108.  
  109.           switch (c)
  110.         {
  111.         case 'f': cmd = u_FILE_SIZE;
  112.           break;
  113. #ifndef SYSV
  114.         case 'a':
  115.           print_all_limits ();
  116.           return (EXECUTION_SUCCESS);
  117.  
  118.         case 'c': cmd = u_CORE_FILE_SIZE;
  119.           break;
  120.  
  121.         case 'd': cmd = u_DATA_SEG_SIZE;
  122.           break;
  123.  
  124.         case 'm': cmd = u_PHYS_MEM_SIZE;
  125.           break;
  126.  
  127.         case 't':
  128.           cmd = u_CPU_TIME_LIMIT;
  129.           block_factor = 1000;
  130.           break;
  131.  
  132.         case 's': cmd = u_STACK_SIZE;
  133.           break;
  134. #endif
  135.         default:
  136.         error_case:
  137. #ifdef SYSV
  138.           report_error("usage: ulimit [-f] [new limit]");
  139. #else
  140.           report_error("usage: ulimit [-cmdstf] [new limit]");
  141. #endif
  142.           return EXECUTION_FAILURE;
  143.         }
  144.         }
  145.       
  146.       /* If an argument was supplied for the command, then we want to
  147.          set the limit. */
  148.       if (list)
  149.         {
  150.           s = list->word->word;
  151.           list = list->next;
  152.           if (sscanf (s, "%ld", &limit) != 1)
  153.         {
  154.           if (strcmp (s, "unlimited") == 0)
  155.             limit = RLIM_INFINITY;
  156.           else
  157.             {
  158.               report_error ("ulimit: bad non-numeric arg `%s'", s);
  159.               return (EXECUTION_FAILURE);
  160.             }
  161.         }
  162.           setting++;
  163.         }
  164.     }
  165.  
  166.       if (limit == RLIM_INFINITY)
  167.     block_factor = 1;
  168.  
  169.       real_limit = limit * block_factor;
  170.  
  171.       current_limit = shell_ulimit (cmd, real_limit, 0);
  172.  
  173.       if (setting)
  174.     {
  175.       /* If we wish to set the limit, we have to make sure that it is
  176.          a "legal" change. */
  177.       if (current_limit < (real_limit))
  178.         {
  179.           report_error("bad ulimit");
  180.           return (EXECUTION_FAILURE);
  181.         }
  182.  
  183.       /* Since the change would be "legal", remember the new child
  184.          resource limit. */
  185.       {
  186.         RESOURCE_LIMIT *newlimit, *limits = resource_limits;
  187.  
  188.         while (limits)
  189.           {
  190.         if (limits->cmd == cmd)
  191.           {
  192.             limits->limit = real_limit;
  193.             return (EXECUTION_SUCCESS);
  194.           }
  195.         limits = limits->next;
  196.           }
  197.         
  198.         newlimit = (RESOURCE_LIMIT *)xmalloc (sizeof (RESOURCE_LIMIT));
  199.  
  200.         newlimit->cmd = cmd;
  201.         newlimit->limit = real_limit;
  202.         newlimit->next = resource_limits;
  203.         resource_limits = newlimit;
  204.         return (EXECUTION_SUCCESS);
  205.       }
  206.     }
  207.       else
  208.     {
  209.       register RESOURCE_LIMIT *limits = resource_limits;
  210.  
  211.       /* If we aren't setting the limit, then we are getting the limit.
  212.          So print the results. */
  213.       while (limits)
  214.         {
  215.           if (limits->cmd == cmd)
  216.         {
  217.           current_limit = resource_limits->limit;
  218.           break;
  219.         }
  220.  
  221.           limits = limits->next;
  222.         }
  223.       
  224.       if (current_limit != RLIM_INFINITY)
  225.         printf ("%ld\n", (current_limit / block_factor));
  226.       else
  227.         printf ("unlimited\n");
  228.     }
  229.     }
  230.   while (list);
  231.   return (EXECUTION_SUCCESS);
  232. }
  233.  
  234. /* The ulimit that we call from within Bash.  Extended to handle
  235.    more resources by Chet Ramey (chet@cwjcc.cwru.edu).
  236.    WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
  237.    contains the desired new limit.  Otherwise, the existing limit is
  238.    returned. */
  239. long
  240. shell_ulimit (which, newlim, setting)
  241.      int which, setting;
  242.      long newlim;
  243. {
  244. #ifndef SYSV
  245.   struct rlimit limit;
  246. #endif
  247.  
  248.   switch (which)
  249.     {
  250.  
  251.     case u_FILE_SIZE:
  252.       if (!setting)
  253.     {
  254. #ifdef SYSV
  255.       return (ulimit (1, 0l));
  256. #else
  257.       if (getrlimit (RLIMIT_FSIZE, &limit) != 0 )
  258.         return ((long) -1);
  259.       return (limit.rlim_cur);
  260. #endif
  261.     }
  262.       else
  263.     {
  264. #ifdef SYSV
  265.       return (ulimit (2, newlim));
  266. #else
  267.       limit.rlim_cur = newlim;
  268.       return (setrlimit (RLIMIT_FSIZE, &limit));
  269. #endif
  270.     }
  271.  
  272. #ifndef SYSV
  273.     case u_MAX_BREAK_VAL:
  274.       if (setting || (getrlimit (RLIMIT_DATA, &limit) != 0))
  275.     return ((long) -1);
  276.       return (limit.rlim_cur);
  277.  
  278.       /* You can't get or set the pipe size with getrlimit. */
  279.     case u_PIPE_SIZE:
  280.       errno = EINVAL;
  281.       return ((long) -1);
  282.  
  283.     case u_CORE_FILE_SIZE:
  284.       if (!setting)
  285.     {
  286.       if (getrlimit (RLIMIT_CORE, &limit) != 0)
  287.         return ((long) -1);
  288.       return (limit.rlim_cur);
  289.     }
  290.       else
  291.     {
  292.       limit.rlim_cur = newlim;
  293.       return (setrlimit (RLIMIT_CORE, &limit));
  294.     }
  295.  
  296.     case u_DATA_SEG_SIZE:
  297.       if (!setting)
  298.     {
  299.       if (getrlimit (RLIMIT_DATA, &limit) != 0)
  300.         return (long) -1;
  301.       return (limit.rlim_cur);
  302.     }
  303.       else
  304.     {
  305.       limit.rlim_cur = newlim;
  306.       return (setrlimit (RLIMIT_DATA, &limit));
  307.     }
  308.  
  309.     case u_PHYS_MEM_SIZE:
  310.       if (!setting)
  311.     {
  312.       if (getrlimit (RLIMIT_RSS, &limit) != 0)
  313.         return ((long) -1);
  314.       return (limit.rlim_cur);
  315.     }
  316.       else
  317.     {
  318.       limit.rlim_cur = newlim;
  319.       return (setrlimit (RLIMIT_RSS, &limit));
  320.     }
  321.  
  322.     case u_CPU_TIME_LIMIT:
  323.       if (!setting)
  324.     {
  325.       if (getrlimit (RLIMIT_CPU, &limit) != 0)
  326.         return ((long) -1);
  327.       return (limit.rlim_cur);
  328.     }
  329.       else
  330.     {
  331.       limit.rlim_cur = newlim;
  332.       return (setrlimit (RLIMIT_CPU, &limit));
  333.     }
  334.  
  335.     case u_STACK_SIZE:
  336.       if (!setting)
  337.     {
  338.       if (getrlimit (RLIMIT_STACK, &limit) != 0)
  339.         return ((long) -1);
  340.       return (limit.rlim_cur);
  341.     }
  342.       else
  343.     {
  344.       limit.rlim_cur = newlim;
  345.       return (setrlimit(RLIMIT_STACK, &limit));
  346.     }
  347. #endif
  348.  
  349.     default:
  350.       errno = EINVAL;
  351.       return ((long) -1);
  352.     }
  353. }
  354.  
  355. #ifndef SYSV
  356.  
  357. #ifndef RLIM_NLIMITS
  358. #define RLIM_NLIMITS    6        /* Number of resource limits */
  359. #endif
  360.  
  361. struct bsd_resource_limits {
  362.     int    limit_param;        /* param to pass to getrlimit() */
  363.     char    *limit_string;        /* de